/*
	Azid Engine is 3D Game Engine developed along side with Galactic Siege (see Google Code) 
	Copyright (C) 2010  Jorgen Ader

	This file is part of AzidEngine.

	AzidEngine is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	AzidEngine is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with AzidEngine.  If not, see <http://www.gnu.org/licenses/>. 
*/

#ifndef __AzidEngine_HPP__
#define __AzidEngine_HPP__

// version 0.0.0 codename Unstable atom
// version 0.0.1 codename Crazy Monky
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define MINOR_SUB_VERSION 0
#define CODE_NAME "Unstable Atom"

#include "Includes.hpp"

namespace AzidEngine
{
	/**
	 * \addtogroup ENGINE
	 * @{
	 * \addtogroup CORE
	 **/

	struct MouseInfo
	{

		bool	mouseLeft;
		bool	mouseRight;
		bool	mouseMiddle;
		bool	mouseButton3;
		bool	mouseButton4;
	};

	struct SensitiveFactor
	{
		Ogre::Real	renderDistanceFactor;
		Ogre::Real	mouseMoveFactor;
	};

	/**
	 * \class AzidGame
	 * @{
	 **/
	class AzidGame : public OIS::KeyListener, OIS::MouseListener
	{
	public:
		Ogre::Root*								Root;
		Ogre::SceneManager*						SceneMgr;
		Ogre::RenderWindow*						RenderWnd;
		Ogre::Camera*							Camera;
		Ogre::Viewport*							Viewport;
		Ogre::Log*								LogMgr;
		Ogre::Timer*							Timer;
		OgreOggSound::OgreOggSoundManager*		SoundMgr;

		OIS::InputManager*						InputMgr;
		OIS::Keyboard*							KeyboardHandler;
		OIS::Mouse*								MouseHandler;

		CEGUI::OgreRenderer						GuiRenderer;
		
		Ogre::String							Skin;
		
		// Engine manager's created when needed, destroyed when not needed anymore
		SettingsManager*						SettingsMgr;
		NetworkManager*							NetworkMgr;
		ObjectManager*							ObjectMgr;
		StateManager*							StateMgr;
		ModManager*								ModMgr;

		/** Starts OGRE and other compnents
		 * @param wndTitle		Set's Main Window Title
		 * @param height		Set's screen height to given parameter
		 * @param width			Set's screen width to given parameter
		 * @param screenMode	Set's screen mode to given parameter
		 */
		void initEngine(Ogre::String wndTitle, int height = 0, int width = 0, short screenmode = -1);

		static void create()
		{
			assert(_this == 0);
			_this = new AzidGame;

			_this->Root = 0;
			_this->RenderWnd = 0;
			_this->Viewport = 0;
			_this->LogMgr = 0;
			_this->Timer = 0;
			_this->SettingsMgr = 0;
			_this->NetworkMgr = 0;
			_this->ObjectMgr = 0;
			_this->StateMgr = 0;
			_this->ModMgr = 0;
		}

		static void destroy()
		{
			assert(_this != 0);
			if(_this->StateMgr != 0)
				delete _this->StateMgr;
			if(_this->ModMgr != 0)
				delete _this->ModMgr;
			if(_this->SoundMgr != 0)
			{
				_this->SoundMgr->stopAllSounds();
				_this->SoundMgr->destroyAllSounds();
				delete _this->SoundMgr;
			}

			_this->GuiRenderer.destroySystem();
			if(_this->KeyboardHandler != 0)
				delete _this->KeyboardHandler;
			if(_this->MouseHandler != 0)
				delete _this->MouseHandler;

			OIS::InputManager::destroyInputSystem(_this->InputMgr);

			if(_this->Root != 0)
				delete _this->Root;
			delete _this;
		}
		
		static AzidGame* getSingletonPtr()
		{
			return _this;
		}

		static AzidGame& getSingleton()
		{
			assert(_this != 0);
			return *_this;
		}

		// TODO add manager creator's here
		static NetworkManager* createNetworkManager(int port)
		{
			assert(_this != 0 && _this->NetworkMgr == 0);
			_this->NetworkMgr = new NetworkManager(port);
			return _this->NetworkMgr;
		}

		static void destroyNetworkManager()
		{
			assert(_this != 0 && _this->NetworkMgr != 0);
			delete _this->NetworkMgr;
			_this->NetworkMgr = 0;
		}

		static ObjectManager* createObjectManager()
		{
			assert(_this != 0 && _this->ObjectMgr == 0);
			_this->ObjectMgr = new ObjectManager;
			return _this->ObjectMgr;
		}

		static void destroyObjectManager()
		{
			assert(_this != 0 &&_this->ObjectMgr != 0);
			delete _this->ObjectMgr;
			_this->ObjectMgr = 0;
		}

		/**
		 * Starts Main RenderLoop
		 **/
		void startGame();
#ifdef _DEBUG
		/**
		 *  Handles DEBUG overlay updating
		 **/
		void debugUpdate();
#endif

		/**
		 * Keyboard event for keyboard button key pressed function
		 * @returns bool true for success, false for failure
		 **/
		bool keyPressed(const OIS::KeyEvent &evt);

		/**
		 * Keyboard event for keyboard button key released function
		 * @returns bool true for success, false for failure
		 **/
		bool keyReleased(const OIS::KeyEvent &evt);

		/**
		 * Mouse event for mouse moved function
		 * @returns bool true for success, false for failure
		 **/
		bool mouseMoved(const OIS::MouseEvent &evt);

		/**
		 *  Mouse event for mouse button pressed function
		 *  @returns bool true for success, false for failure
		 **/
		bool mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id);

		/**
		 *  Mouse event for mouse button released function
		 *  @returns bool true for success, false for failure
		 **/
		bool mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id);
		
		/**
		 * Quit action handler
		 **/
		void actionQuit();
		
		/**
		 * Creates screenshot and saves it as <i>screenshot_\<<i>current date</i>\>_\<<i>current time</i>\>.png</i>
		 **/
		void makeScreenShot();
	private:
		// Private Singleton declaration's
		/**
		 * private AzidEngine main class constructor
		 **/
		AzidGame();

		/**
		 * AzidEngine Destructor
		 **/
		~AzidGame();

		static AzidGame*	_this;

		// Preventing copying & assigning
		AzidGame( const AzidGame& );
		AzidGame& operator=( const AzidGame& );

		bool						mQuit;
		bool						mConsoleActive;

		std::vector<Ogre::String>	mBgSoundList; // Maybe it should be OgreOggSound*, will use less memory then

		/* Sensitivity Factors */
		SensitiveFactor				mSensFactor;

		/* Mouse buttons */
		MouseInfo					mMouseInfo;

#ifdef _DEBUG
		Ogre::Overlay*				mDebugOverlay;
#endif
	};
	/**
	 * @}
	 * @}
	 * @}
	 */
}
#endif
